﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Styx;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Styx.Pathing;
using Styx.Common;
using System.Windows.Media;
using Styx.CommonBot.Frames;
using System.Diagnostics;

namespace Guardian
{
    public partial class Combat : CombatRoutine
    {
        Composite KatRotation()
        {
            return new PrioritySelector(
                Cast(CAT_FORM, ret => Me.Shapeshift != ShapeshiftForm.Cat && (!buffExists(MIGHT_OF_URSOC, Me) && !SwitchBearForm) || PauseAoe),
                new Decorator(ret => Me.HealthPercent <= SettingsCat.myPrefs.PercentHealthstone && nextHealthstoneUseAllowed <= DateTime.Now, HealthstoneCat()),
                new Decorator(ret => gotTarget && AutoBot && UnfriendlyUnits.Count() > 0 && Me.CurrentTarget.Distance >= 12, new Action(ret => { Me.ClearTarget(); return RunStatus.Failure; })),
                new Decorator(ret => gotTarget
                    && Me.ComboPoints == 4
                    && (debuffExists(RIP, Me.CurrentTarget) && debuffTimeLeft(RIP, Me.CurrentTarget) <= 6000)
                    && buffExists(PREDATORY_SWIFTNESS, Me)
                    && nextHealingTouchAllowed <= DateTime.Now, CastHealingTouch()),
                new Decorator(ret => gotTarget
                    && Me.ComboPoints == 4
                    && buffExists(DREAM_OF_CENARIUS, Me)
                    && (debuffExists(RAKE, Me.CurrentTarget) && debuffTimeLeft(RAKE, Me.CurrentTarget) <= 4000)
                    && nextRakeAllowed <= DateTime.Now, CastRakeDoC()),
                new Decorator(ret => gotTarget
                    && Me.ComboPoints >= 5
                    && buffExists(DREAM_OF_CENARIUS, Me)
                    && (debuffExists(RIP, Me.CurrentTarget) && debuffTimeLeft(RIP, Me.CurrentTarget) <= 6000), CastRiPDoC()),
                new Decorator(ret => Me.ComboPoints <= 3
                    && SettingsCat.myPrefs.HealOthers
                    && Me.HealthPercent >= SettingsCat.myPrefs.PercentHealOthers
                    && buffExists(PREDATORY_SWIFTNESS, Me)
                    && (Me.CurrentMap.IsRaid 
                    || Me.CurrentMap.IsDungeon 
                    || Me.CurrentMap.IsScenario 
                    || Me.CurrentMap.IsInstance 
                    || Me.CurrentMap.IsBattleground
                    || Me.CurrentMap.IsArena
                    || Me.GroupInfo.IsInRaid 
                    || Me.GroupInfo.IsInParty)
                    && nextHealingTouchAllowed <= DateTime.Now, HealPartyMember()),
                new Decorator(ret => Me.ComboPoints <= 3
                    && !SettingsCat.myPrefs.HealOthers
                    && (buffExists(PREDATORY_SWIFTNESS, Me) && buffTimeLeft(PREDATORY_SWIFTNESS, Me) >= 2000)
                    && nextHealingTouchAllowed <= DateTime.Now, CastHealingTouch()),
                new Decorator(ret => MeIsSolo
                    && Me.ComboPoints <= 3
                    && (buffExists(PREDATORY_SWIFTNESS, Me) && buffTimeLeft(PREDATORY_SWIFTNESS, Me) >= 2000)
                    && nextHealingTouchAllowed <= DateTime.Now, CastHealingTouch()),
                new Decorator(ret => !Me.CurrentMap.IsArena
                    && SettingsBear.myPrefs.AutoResTank
                    && (Me.CurrentMap.IsRaid || Me.CurrentMap.IsDungeon || Me.CurrentMap.IsScenario || Me.CurrentMap.IsInstance || Me.GroupInfo.IsInRaid || Me.GroupInfo.IsInParty)
                    && AnyTankNearby
                    && !spellOnCooldown(REBIRTH), ResTank()),
                new Decorator(ret => !Me.CurrentMap.IsArena
                    && SettingsBear.myPrefs.AutoResHealer
                    && (Me.CurrentMap.IsRaid || Me.CurrentMap.IsDungeon || Me.CurrentMap.IsScenario || Me.CurrentMap.IsInstance || Me.GroupInfo.IsInRaid || Me.GroupInfo.IsInParty)
                    && AnyHealerNearby
                    && !spellOnCooldown(REBIRTH), ResHealer()),
                Cast(BARKSKIN, ret => gotTarget
                    && GetSpellCooldown(BARKSKIN).TotalSeconds < 1
                    && Me.HealthPercent <= SettingsCat.myPrefs.PercentBarkskin
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast(FRENZIED_REGENERATION, ret => gotTarget
                    && SpellManager.HasSpell(FRENZIED_REGENERATION)
                    && GetSpellCooldown(FRENZIED_REGENERATION).TotalSeconds < 1
                    && Me.HealthPercent <= SettingsCat.myPrefs.PercentFrenziedRegeneration),
                Cast(SURVIVAL_INSTINCTS, ret => gotTarget
                    && SpellManager.HasSpell(SURVIVAL_INSTINCTS)
                    && GetSpellCooldown(SURVIVAL_INSTINCTS).TotalSeconds < 1
                    && Me.HealthPercent <= SettingsCat.myPrefs.PercentSurvivalInstincts),
                new Decorator(ret => IsRooted(Me), RemoveRooted()),
                
                //CatAoe
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell(SWIPE)
                    && !PauseAoe 
                    && UnfriendlyUnits.Count() >= SettingsCat.myPrefs.startCatAoe,
                    new PrioritySelector(
                        Cast(CAT_FORM, ret => Me.Shapeshift != ShapeshiftForm.Cat),
                        new Decorator(ret => gotTarget
                            && SpellManager.HasSpell(SAVAGE_ROAR)
                            && Me.EnergyPercent > 25
                            && !buffExists(SAVAGE_ROAR, Me) 
                            && (SettingsCat.myPrefs.HaveGlyphOfSavagery && Me.ComboPoints >= 0)
                            && nextSavageRoarAllowed <= DateTime.Now, CastSavageRoar()),
                        new Decorator(ret => gotTarget
                            && SpellManager.HasSpell(SAVAGE_ROAR)
                            && Me.EnergyPercent > 25
                            && !buffExists(SAVAGE_ROAR, Me) 
                            && Me.ComboPoints > 0
                            && nextSavageRoarAllowed <= DateTime.Now, CastSavageRoar()),
                        new Decorator(ret => gotTarget && SpellManager.HasSpell(TIGERS_FURY) 
                            && Me.EnergyPercent < 30 
                            && nextTigerFuryAllowed <= DateTime.Now, CastTigersFury()),
                        new Decorator(ret => gotTarget
                            && SpellManager.HasSpell(LIFEBLOOD)
                            && GetSpellCooldown(LIFEBLOOD).TotalSeconds < 1
                            && IsWoWBoss(Me.CurrentTarget)
                            && NotHaveHasteBuffs
                            && Me.CurrentTarget.IsWithinMeleeRange, LifeBlood()),
                        Cast(THRASH, ret => !debuffExists(THRASH, Me.CurrentTarget)
                            && Me.EnergyPercent > 50 || debuffExists(CLEARCASTING, Me)),
                        Cast(SWIPE)
                        )),
                //start Cat combat
                new Decorator(ret => gotTarget && !buffExists(MIGHT_OF_URSOC, Me) && !SwitchBearForm,
                    new PrioritySelector(
                Cast(CAT_FORM, ret => Me.Shapeshift != ShapeshiftForm.Cat),
                new Decorator(ret => gotTarget && Me.EnergyPercent < 30 && NeedTigersFury && nextTigerFuryAllowed <= DateTime.Now, CastTigersFury()),
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell(THRASH)
                    && (!buffExists(DREAM_OF_CENARIUS, Me) || Me.ComboPoints <= 3)
                    && buffExists(CLEARCASTING, Me)
                    && !debuffExists(THRASH, Me.CurrentTarget)
                    && nextThrashAllowed <= DateTime.Now, CastThrash()),
                Cast(RIP, ret => gotTarget
                    && IsWoWBoss(Me.CurrentTarget)
                    && Me.ComboPoints >= 5
                    && Me.EnergyPercent >= 30
                    && (!debuffExists(RIP, Me.CurrentTarget)
                    || debuffTimeLeft(RIP, Me.CurrentTarget) <= 4500)),
                Cast(FEROCIOUS_BITE, ret => gotTarget
                    && IsWoWBoss(Me.CurrentTarget)
                    && debuffExists(RIP, Me.CurrentTarget) && (debuffTimeLeft(RIP, Me.CurrentTarget) > 4500 || Me.CurrentTarget.HealthPercent < 25)
                    && Me.ComboPoints >= 5
                    && Me.EnergyPercent > 25),
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell(SAVAGE_ROAR)
                    && Me.EnergyPercent > 25
                    && !buffExists(SAVAGE_ROAR, Me)
                    && (SettingsCat.myPrefs.HaveGlyphOfSavagery && Me.ComboPoints >= 0)
                    && nextSavageRoarAllowed <= DateTime.Now, CastSavageRoar()),
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell(SAVAGE_ROAR)
                    && Me.EnergyPercent > 25
                    && !buffExists(SAVAGE_ROAR, Me)
                    && Me.ComboPoints > 0
                    && nextSavageRoarAllowed <= DateTime.Now, CastSavageRoar()),
                Cast(RAKE, ret => gotTarget 
                    && !debuffExists(RAKE, Me.CurrentTarget)
                    || debuffTimeLeft(RAKE, Me.CurrentTarget) <= 2500
                    && Me.EnergyPercent > 35),
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell(SKULL_BASH)
                    && GetSpellCooldown(SKULL_BASH).TotalSeconds < 1
                    && Me.CurrentTarget.IsCasting
                    && Me.CanInterruptCurrentSpellCast
                    && nextInterruptAllowed <= DateTime.Now, SkullBash()),
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell(WAR_STOMP)
                    && !spellOnCooldown(WAR_STOMP)
                    && Me.CurrentTarget.IsCasting
                    && !Me.CanInterruptCurrentSpellCast
                    && nextStunAllowed <= DateTime.Now, WarStomp()),
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell(MIGHTY_BASH)
                    && !spellOnCooldown(MIGHTY_BASH)
                    && Me.CurrentTarget.IsCasting 
                    && !Me.CanInterruptCurrentSpellCast
                    && nextStunAllowed <= DateTime.Now, MightyBash()),
                Cast(BERSERK, ret => gotTarget 
                    && SpellManager.HasSpell(BERSERK)
                    && GetSpellCooldown(BERSERK).TotalSeconds < 1
                    && IsWoWBoss(Me.CurrentTarget)
                    && Me.CurrentTarget.IsWithinMeleeRange),
                new Decorator(ret => SpellManager.HasSpell(FORCE_OF_NATURE)
                    && gotTarget
                    && nextFoNCastAllowed <= DateTime.Now, CastFoN()),
                Cast(INCARNATION, ret => gotTarget
                    && SpellManager.HasSpell(INCARNATION)
                    && GetSpellCooldown(INCARNATION).TotalSeconds < 1
                    && IsWoWBoss(Me.CurrentTarget)
                    && Me.CurrentTarget.IsWithinMeleeRange),
                new Decorator(ret => SettingsCat.myPrefs.Trinket1Use != SettingsCat.TrinketsUse.Manual 
                    && nextTrinketTimeAllowed <= DateTime.Now
                    && Me.CurrentTarget.IsWithinMeleeRange, Trinket1()),
                new Decorator(ret => SettingsCat.myPrefs.Trinket2Use != SettingsCat.TrinketsUse.Manual 
                    && nextTrinketTimeAllowed <= DateTime.Now
                    && Me.CurrentTarget.IsWithinMeleeRange, Trinket2()),
                new Decorator(ret => gotTarget && nextSymbiosisSpellCastAllowed <= DateTime.Now, CastFeralSymbiosis()),
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell(LIFEBLOOD)
                    && GetSpellCooldown(LIFEBLOOD).TotalSeconds < 1
                    && IsWoWBoss(Me.CurrentTarget)
                    && NotHaveHasteBuffs
                    && Me.CurrentTarget.IsWithinMeleeRange, LifeBlood()),
                Cast(BERSERKING, ret => gotTarget
                    && SpellManager.HasSpell(BERSERKING)
                    && GetSpellCooldown(BERSERKING).TotalSeconds < 1
                    && IsWoWBoss(Me.CurrentTarget)
                    && NotHaveHasteBuffs
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast(RAVAGE, ret => gotTarget
                    && SpellManager.HasSpell(RAVAGE)
                    && buffExists(INCARNATION, Me)),
                Cast(SHRED, ret => gotTarget
                    && (debuffExists(RAKE, Me.CurrentTarget) || debuffExists(THRASH, Me.CurrentTarget))
                    && Me.IsSafelyBehind(Me.CurrentTarget) || (SettingsCat.myPrefs.HaveGlyphOfShred && (buffExists(TIGERS_FURY, Me) || buffExists(BERSERK, Me)))
                    && Me.EnergyPercent > 40),
                Cast(FEROCIOUS_BITE, ret => gotTarget
                    && !IsWoWBoss(Me.CurrentTarget)
                    && Me.ComboPoints >= 3
                    && Me.EnergyPercent > 25),
                Cast(MANGLE, ret => gotTarget && Me.EnergyPercent > 35 && Me.ComboPoints < 5)))
                );
        }

        #region rakeDoC
        private DateTime nextRakeAllowed;

        public void SetNextNextRakeAllowed()
        {
            nextRakeAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 1000);
        }
        Composite CastRakeDoC()
        {
            return new Action(ret =>
            {
                if (SpellManager.CanCast(RAKE))
                {
                    SpellManager.Cast(RAKE);
                    Logging.Write(Colors.DeepPink, RAKE + " DoC");
                    SetNextNextSavageRoarAllowed();
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            });
        }
        #endregion

        #region ripDoC
        Composite CastRiPDoC()
        {
            return new Action(ret =>
            {
                if (SpellManager.CanCast(RIP))
                {
                    SpellManager.Cast(RIP);
                    Logging.Write(Colors.DeepPink, RIP + " DoC");
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            });
        }

        #endregion

        #region savage roar
        private DateTime nextSavageRoarAllowed;

        public void SetNextNextSavageRoarAllowed()
        {
            nextSavageRoarAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 1000);
        }
        
        Composite CastSavageRoar()
        {
            return new Action(ret =>
            {
                if (SpellManager.CanCast(SAVAGE_ROAR))
                {
                    SpellManager.Cast(SAVAGE_ROAR);
                    Logging.Write(Colors.Bisque, SAVAGE_ROAR);
                    SetNextNextSavageRoarAllowed();
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            });
        }
        #endregion

        #region Tiger's fury
        private DateTime nextTigerFuryAllowed;

        public void SetNextNextTigerFuryAllowed()
        {
            nextTigerFuryAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 1500);
        }
        public bool NeedTigersFury
        {
            get
            {
                if (!SpellManager.HasSpell(TIGERS_FURY))
                {
                    return false;
                }
                if (buffExists(TIGERS_FURY, Me)
                    || buffExists(HEROISM, Me)
                    || buffExists(BERSERK, Me)
                    || buffExists(TIME_WARP, Me)
                    || buffExists(BLOODLUST, Me)
                    || buffExists(DRUMS_OF_RAGE, Me)
                    || buffExists(ANCIENT_HYSTERIA, Me))
                {
                    return false;
                }
                if (!buffExists(TIGERS_FURY, Me) && !spellOnCooldown(TIGERS_FURY))
                {
                    return true;
                }
                return false;
            }
        }
        Composite CastTigersFury()
        {
            return new Action(ret =>
            {
                if (SpellManager.CanCast(TIGERS_FURY))
                {
                    SpellManager.Cast(TIGERS_FURY);
                    Logging.Write(Colors.Bisque, TIGERS_FURY);
                    SetNextNextTigerFuryAllowed();
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            });
        }
        #endregion

        #region thrash
        private DateTime nextThrashAllowed;

        public void SetNextNextThrashAllowed()
        {
            nextThrashAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 1500);
        }
        Composite CastThrash()
        {
            return new Action(ret =>
            {
                if (SpellManager.CanCast(THRASH))
                {
                    SpellManager.Cast(THRASH);
                    Logging.Write(Colors.DeepPink, THRASH);
                    SetNextNextThrashAllowed();
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            });
        }
        #endregion

        #region need go backwards
        Composite GoBackwards()
        {
            return
                new Action(ret =>
                {

                    WoWMovement.Move(WoWMovement.MovementDirection.Backwards);
                    while (gotTarget && Me.CurrentTarget.IsAlive && Me.CurrentTarget.Distance <= 10)
                    {
                        break;
                    }
                    WoWMovement.MoveStop();
                    return RunStatus.Failure;
                });
        }
        #endregion

        #region Cast Feral Symbiosis
        private DateTime nextSymbiosisSpellCastAllowed;

        public void SetNextSymbiosisSpellCastAllowed()
        {
            nextSymbiosisSpellCastAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 1000);
        }
        Composite CastFeralSymbiosis()
        {
            return new Action(ret =>
            {
                if (SpellManager.HasSpell("Death Coil")
                    && !spellOnCooldown("Death Coil")
                    && Me.EnergyPercent >= 75
                    && SpellManager.CanCast("Death Coil"))
                {
                    SpellManager.Cast("Death Coil");
                    Logging.Write(Colors.DeepPink, "Death Coil");
                    SetNextSymbiosisSpellCastAllowed();
                    return RunStatus.Success;
                }
                if (SpellManager.HasSpell("Feral Spirit")
                    && !spellOnCooldown("Feral Spirit")
                    && SpellManager.CanCast("Feral Spirit"))
                {
                    SpellManager.Cast("Feral Spirit");
                    Logging.Write(Colors.DeepPink, "Feral Spirit");
                    SetNextSymbiosisSpellCastAllowed();
                    return RunStatus.Success;
                }
                if (SpellManager.HasSpell("Dispersion")
                    && !spellOnCooldown("Dispersion")
                    && Me.HealthPercent <= 35
                    && SpellManager.CanCast("Dispersion"))
                {
                    SpellManager.Cast("Dispersion");
                    Logging.Write(Colors.DeepPink, "Dispersion");
                    SetNextSymbiosisSpellCastAllowed();
                    return RunStatus.Success;
                }
                if (SpellManager.HasSpell("Clash")
                    && !spellOnCooldown("Clash")
                    && (Me.CurrentTarget.Distance >= 8 && Me.CurrentTarget.Distance <= 40)
                    && SpellManager.CanCast("Clash"))
                {
                    SpellManager.Cast("Clash", Me.CurrentTarget);
                    Logging.Write(Colors.DeepPink, "Clash");
                    SetNextSymbiosisSpellCastAllowed();
                    return RunStatus.Success;
                }
                if (SpellManager.HasSpell("Divine Shield")
                    && !spellOnCooldown("Divine Shield")
                    && Me.HealthPercent <= 35
                    && SpellManager.CanCast("Divine Shield"))
                {
                    SpellManager.Cast("Divine Shield");
                    Logging.Write(Colors.DeepPink, "Divine Shield");
                    SetNextSymbiosisSpellCastAllowed();
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            });
        }
        #endregion

    }
}
